//
//  XDModel.m
//  XDFS
//
//  Created by Yury Soldak on 30/09/2008.
//

#import "XDModel.h"

@interface XDModel (Private)
- (NSXMLDocument*) fetchXML: (NSString*) url;
- (void) parseXMLAndInitMaps;
@end

@interface NSXMLNode (SingleNode)
- (NSString*) stringValueOfNodeForXPath:(NSString*) path;
@end


#pragma mark Public methods implementation

@implementation XDModel

- (id) initWithURLString: (NSString*) url {
	if (self = [super init]) {
		doc = [self fetchXML: url];
		[self parseXMLAndInitMaps];
	}
	return self;
}

- (void) dealloc {
	[doc release];
	[href2name release];
	[href2tags release];
	[tag2hrefs release];
	[super dealloc];
}

- (NSString*) nameForHref: (NSString*) href {
	return [href2name objectForKey:href];
}

- (NSString*) hrefForName: (NSString*) name {
	for (NSString* href in [href2name allKeys]) {
		NSString* tname = [href2name objectForKey:href];
		if ([tname isEqualToString:name]) {
			return href;
		}
	}
	return nil;
}

- (NSSet*) tagsForHref: (NSString*) href {
	return [href2tags objectForKey:href];
}

- (NSSet*) hrefsForTag: (NSString*) tag {
	return [tag2hrefs objectForKey:tag];
}

- (NSSet*) hrefsForTags: (NSSet*) tags {
	NSMutableSet* result = [NSMutableSet set];
	for (NSString *tag in tags) {
		NSSet* hrefs = [self hrefsForTag:tag];
		if ([result count] == 0) {
			[result unionSet:hrefs];
		} else {
			[result intersectSet:hrefs];
		}
	}
	return result;
}

- (NSSet*) allTags {
	return [NSSet setWithArray:[tag2hrefs allKeys]];
}

@end

#pragma mark Private methods implementation

@implementation XDModel (Private)

- (NSXMLDocument*) fetchXML:(NSString*) url {
	NSURLRequest* request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
	NSURLResponse* response = nil;
	NSError* error = nil;
	NSData* data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
	if (data == nil) {
		NSRunAlertPanel(@"DeliciousFS Error", @"Unable to download data.", @"Quit", nil, nil);
		exit(1);
	}
	NSXMLDocument* xdoc = [[NSXMLDocument alloc] initWithData:data options:0 error:&error];  
	[xdoc autorelease];
	return xdoc;
}

- (void) parseXMLAndInitMaps {
	NSError* error = nil;
	NSArray* posts = [[doc rootElement] nodesForXPath:@".//post" error:&error];
	// TODO: error handling
	
	href2tags = [[NSMutableDictionary alloc] init];
	href2name = [[NSMutableDictionary alloc] init];
	tag2hrefs = [[NSMutableDictionary alloc] init];
	for (NSXMLNode* post in posts) {
		NSString* href = [post stringValueOfNodeForXPath:@"./@href"];
		NSString* desc = [post stringValueOfNodeForXPath:@"./@description"];
		NSString* tagString = [post stringValueOfNodeForXPath:@"./@tag"];
		NSArray* tags = [tagString componentsSeparatedByString:@" "];
		[href2tags setValue:tags forKey:href];
		[href2name setValue:desc forKey:href];
		for (NSString* tag in tags) {
			NSMutableSet* hrefs = [tag2hrefs objectForKey:tag];
			if (!hrefs) {
				hrefs = [NSMutableSet set];
				[tag2hrefs setValue:hrefs forKey:tag];
			}
			[hrefs addObject:href];
		}
	}
}

@end

@implementation NSXMLNode (SingleNode)
- (NSString*) stringValueOfNodeForXPath:(NSString*) path {
	NSError* error = nil;
	NSArray* tmpArray = [self nodesForXPath:path error:&error];
	if (error) {
		exit(1);
	}
    NSString* result = [[tmpArray objectAtIndex:0] stringValue];
	return result;
}
@end

